package com.bn.feeds.processor;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FilenameUtils;

import atg.core.util.StringUtils;
import atg.nucleus.GenericService;
import au.com.bytecode.opencsv.CSVReader;

public class DeltaFeedProcessor extends GenericService{

	private static char feedColumnSeperator = '^';

	public char getFeedColumnSeperator() {
		return feedColumnSeperator;
	}


	public void setFeedColumnSeperator(char feedColumnSeperator) {
		this.feedColumnSeperator = feedColumnSeperator;
	}

	public static void main(String args[]) {
		DeltaFeedProcessor feedProcessor = new DeltaFeedProcessor();
		String currentFilePath = "/opt/app/feeds/inbound/catalog/sku/process";
		String previousFilePath1 = "/opt/app/feeds/inbound/catalog/sku/processed";
		String archiveFilePath = "/opt/app/feeds/inbound/catalog/sku/archive";
		String deltaArchivePath= "/opt/app/feeds/inbound/catalog/sku/delta_archive";
		
		boolean currentFileExists = feedProcessor.isFileExists(currentFilePath);
		if(!currentFileExists){
			System.out.println("There are no files to process in "+currentFilePath);
			return;
		}
		
		Map<String, List<String[]>> previousDataMap =null;
		Map<String, List<String[]>> currentDataMap=null;
		try {
			previousDataMap = feedProcessor.getDataMap(previousFilePath1,archiveFilePath);
			currentDataMap = feedProcessor.getDataMap(currentFilePath,previousFilePath1);
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		
		
		
		if(previousDataMap!=null && currentDataMap!=null)
		{
			Map<String, String> currentValues = feedProcessor.getKeyValues(currentDataMap);
			Map<String, String> previousValues = feedProcessor.getKeyValues(previousDataMap);
			try {
				feedProcessor.compareMapValues (currentValues,previousValues,currentDataMap,currentFilePath);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		} else {
			System.out.println("There is no data to process");
		}
			
		
	}

	public boolean isFileExists(String filePath){
		File folder = new File(filePath);
		File[] feedFiles = folder.listFiles();
		if(feedFiles !=null && feedFiles.length > 0){
			return true;
		}
		return false;
	}
	
	public  Map<String, List<String[]>> getDataMap (String filePath, String archivePath) throws IOException{
		if(isLoggingDebug()){
			logDebug("Start::getDataMap"+filePath);
		}
		String feedName = "";
		Map<String, List<String[]>> dataMap = null;
		File folder = new File(filePath);
		File[] feedFiles = folder.listFiles();
		if(feedFiles !=null && feedFiles.length > 0){
			for(File feedFile:feedFiles){
				if(feedFile.isDirectory()){
					continue;
				}
				feedName = feedFile.getName();
				String fileType = FilenameUtils.getExtension(feedName);
				dataMap = parseFile(feedFile, fileType);
				archiveFile(archivePath, feedFile);
			}
		} else {
			logInfo("Files not found in the path:"+filePath);
		}
		if(isLoggingDebug()){
			logDebug("End::getDataMap"+filePath);
		}
		return dataMap;
	}

	private  Map<String, List<String[]>> parseFile(File file, String fileType) throws IOException{
		if(fileType.equalsIgnoreCase("txt")){
			return getCSVData(file);
		}else if(fileType.equalsIgnoreCase("XML")){
			logInfo("NO XMl");
		}
		return null;
	}

	public Map<String, String> getKeyValues (Map<String, List<String[]>> dataMap){
		Map<String, String> keyValueMap = new HashMap<String, String>();
		List<String[]> data = dataMap.get("data");
		for(String[] str:data){
			String[] key = str[0].split("\\|");
			keyValueMap.put(key[0], str[0]);
		}
		return keyValueMap;
	}

	public void compareMapValues (Map<String, String> currentValueMap, Map<String, String> previousValueMap,Map<String, List<String[]>> currentDataMap,String processPath) throws IOException{
		if(isLoggingDebug()){
			logDebug("Start::compareMapValues");
		}
		DateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
    	DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    	Date currDate = new Date();
		
    	if (!processPath.endsWith("\\") && !processPath.endsWith("/")) {
    		processPath += File.separatorChar;
        }
    	
		String outPutFilePath = processPath+"delta_"+formatter.format(currDate) +".txt";
			File file = new File (outPutFilePath);
			FileWriter fileWriter = new FileWriter(file.getAbsoluteFile());
			BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
			List<String[]> header=currentDataMap.get("header");
			List<String[]> columnNames=currentDataMap.get("columnNames");
			
			String headerValue="";
			for(String str:header.get(0)){
				if(!StringUtils.isBlank(headerValue)){
					headerValue=headerValue+"|";
				}
				headerValue=headerValue+str;
			}
			
			String columnValue="";
			for(String str:columnNames.get(0)){
				if(!StringUtils.isBlank(columnValue)){
					columnValue=columnValue+"|";
				}
				columnValue=columnValue+str;
			}
			
			bufferedWriter.write(headerValue);
			bufferedWriter.write("\n");
			bufferedWriter.write(columnValue);
			bufferedWriter.write("\n");
			for(Map.Entry<String, String> entry : currentValueMap.entrySet()){
				
				String currentValue = entry.getValue();
				String previousValue = previousValueMap.get(entry.getKey());
				if (StringUtils.isBlank(previousValue) || !currentValue.equals(previousValue)){
					
					bufferedWriter.write(currentValue);
					bufferedWriter.write("\n");
				}
			}
			List<String[]> footer=currentDataMap.get("footer");
			String footerValue="";
			for(String str:footer.get(0)){
				if(!StringUtils.isBlank(footerValue)){
					footerValue=footerValue+"|";
				}
				footerValue=footerValue+str;
			}
			bufferedWriter.write(footerValue);
			bufferedWriter.write("\n");
			bufferedWriter.close();
			fileWriter.close();
			if(isLoggingDebug()){
				logDebug("End::compareMapValues");
			}

	}
	private Map<String, List<String[]>> getCSVData(File dataFile) throws IOException {

		Map<String, List<String[]>> dataMap = null;
		CSVReader csvReader = null;
		List<String[]> csvData = null;


		if (dataFile != null) {
			InputStreamReader reader = new InputStreamReader(new FileInputStream(dataFile), Charset.forName("UTF-8"));
			csvReader = new CSVReader(reader, feedColumnSeperator, '\0', '\0', 0, false, false);
			csvData = csvReader.readAll();

			if (csvData.size() > 3) {
				List<String[]> header = new ArrayList<String[]>();
				List<String[]> columnNames = new ArrayList<String[]>();
				List<String[]> footer = new ArrayList<String[]>();
				dataMap = new HashMap<String, List<String[]>>();
				header.add(csvData.get(0));
				dataMap.put("header",header);
				
				columnNames.add(csvData.get(1));
				dataMap.put("columnNames",columnNames);
				
				footer.add(csvData.get(csvData.size()-1));
				dataMap.put("footer",footer);

				
				
				csvData.remove(0);
				csvData.remove(0);
				csvData.remove(csvData.size()-1);

				dataMap.put("data", csvData);
				
				
			} else {
				if(isLoggingDebug()){
					logDebug("is empty or contains just header");	
				}
				
			}
			reader.close();
			csvReader.close();
		} else {
			if(isLoggingDebug()){
				logDebug("Recieved null file dataFile");	
			}
		}

	
		return dataMap;
	}
	
	public void archiveFile(final String directoryPath, final File originalFile) {
        if (!StringUtils.isBlank(directoryPath) && originalFile != null) {
            File file = new File(directoryPath);
            if (!file.exists()) {
                file.mkdirs();
            }
            String path = directoryPath;
            if (!directoryPath.endsWith("\\") && !directoryPath.endsWith("/")) {
                path += File.separatorChar;
            }
            path += originalFile.getName();
            originalFile.renameTo(new File(path));
        }
    }
	
	public void testDelta() throws IOException{
		DeltaFeedProcessor feedProcessor = new DeltaFeedProcessor();
		String currentFilePath = "/opt/app/feeds/inbound/catalog/sku/process";
		String previousFilePath1 = "/opt/app/feeds/inbound/catalog/sku/processed";
		String archiveFilePath = "/opt/app/feeds/inbound/catalog/sku/archive";
		String deltaArchivePath= "/opt/app/feeds/inbound/catalog/sku/delta_archive";
		
		boolean currentFileExists = feedProcessor.isFileExists(currentFilePath);
		if(!currentFileExists){
			System.out.println("There are no files to process in "+currentFilePath);
			return;
		}
		
		Map<String, List<String[]>> previousDataMap = feedProcessor.getDataMap(previousFilePath1,archiveFilePath);
		Map<String, List<String[]>> currentDataMap = feedProcessor.getDataMap(currentFilePath,previousFilePath1);
		
		
		
		if(previousDataMap!=null && currentDataMap!=null)
		{
			Map<String, String> currentValues = feedProcessor.getKeyValues(currentDataMap);
			Map<String, String> previousValues = feedProcessor.getKeyValues(previousDataMap);
			feedProcessor.compareMapValues (currentValues,previousValues,currentDataMap,currentFilePath);
			
		} else {
			logInfo("There is no data to process");
		}
	}
}

